#include "NodeVisitor.h"

#define ABS_INT_MAX (long long)2147483648

using namespace std;

WeedingVisitor::WeedingVisitor(string tn) : NodeVisitor(NodeVisitor::Pre), isValid(true), typeName(tn), isClass(false), constructorCount(0) {};

void WeedingVisitor::visit(CompilationUnitNode *) {
	if (isClass) isValid &= constructorCount > 0;
}

void WeedingVisitor::visit(ClassDeclarationNode *n) {
	static unsigned char validaccess = ModifiedNode::Public | ModifiedNode::Protected;
	static unsigned char validmods = ModifiedNode::Abstract | ModifiedNode::Final;

	isClass = true;

	//Check for proper modifiers and that the name matches the filename
	isValid &= n->CheckModifiers(validaccess, validmods) && n->identifier == typeName;
}
void WeedingVisitor::visit(FieldDeclarationNode *n) {
	static unsigned char validaccess = ModifiedNode::Public | ModifiedNode::Protected;
	static unsigned char validmods = ModifiedNode::Static;
	isValid &= n->CheckModifiers(validaccess, validmods);
}
void WeedingVisitor::visit(MethodDeclarationNode *n) {
	static unsigned char validaccess = ModifiedNode::Public | ModifiedNode::Protected;
	static unsigned char validmods = ModifiedNode::Abstract | ModifiedNode::Native | ModifiedNode::Final | ModifiedNode::Static;
	isValid &= n->CheckModifiers(validaccess, validmods);
	if (!(n->modifier & ModifiedNode::Abstract || n->modifier & ModifiedNode::Native)) isValid &= n->HasChildOfType("Block");
	else if (n->modifier & ModifiedNode::Abstract || n->modifier & ModifiedNode::Native) isValid &= !n->HasChildOfType("Block");
}
void WeedingVisitor::visit(ConstructorDeclarationNode *n) {
	static unsigned char validaccess = ModifiedNode::Public | ModifiedNode::Protected;
	++constructorCount;
	isValid &= ((LeafNode*)(*n)["identifier"])->lexeme == typeName;
	n->DeleteLeafs();
	isValid &= n->CheckModifiers(validaccess, 0x0);
}
void WeedingVisitor::visit(InterfaceDeclarationNode *n) {
	static unsigned char validaccess = ModifiedNode::Public;
	isValid &= n->CheckModifiers(validaccess, 0x0) && n->identifier == typeName;
}
void WeedingVisitor::visit(AbstractMethodDeclarationNode *n) {
	static unsigned char validaccess = ModifiedNode::Public | ModifiedNode::Protected;
	static unsigned char validmods = ModifiedNode::Abstract;
	isValid &= n->CheckModifiers(validaccess, validmods);
}

void WeedingVisitor::visit(IntegerLiteralNode *n) {
	ParentNode *p = n->parent->parent;

	//Resolve the value temporarily
	long long v = n->value;
	if (p->Type() == "UnaryExpression") v *= -1;

	//Check range
	isValid &= v >= -ABS_INT_MAX && v < ABS_INT_MAX;
}

void WeedingVisitor::visit(CastExpressionNode *n) {
	//Casting Expressions are typed. So, the only child should be the one that describes what gets casted. If there is more than one, then something didn't resolve to a type
	isValid &= n->children.size() == 1;
}
